--[[
  192.168.72.16:17100 esb (基于HTTP协议,注意传输的是二进制形式的XML)
]]
require("apm_core");
require("ApmXml");

local G_DEBUG = false

if G_DEBUG == false then
    function logDebug(fmt,...) end
    function logInfo(fmt,...) end
    function logWarn(fmt,...) end
    function logError(fmt,...) end
    function logFatal(fmt,...) end
end

local t_xml_tree;
local s_seq_no
local s_type_name
local s_channel_id
local s_rspcode
local s_rspmsg
local s_message_req
local s_message_resp

local function parseIp(ip)
    local _, _, value = string.find(ip, "(%d+.%d+)$");
    return value == nil and "" or value
end

--- 协议判断
-- return
-- true; false
local function protocol_detect(s_payload)
    if s_payload == nil then return false end;

    t_xml_tree = ApmXml.load(s_payload);

    return ApmXml.getValue(t_xml_tree, "/service") ~= nil;
end

local arr_channel_id = {}


--- 解析请求
-- return
-- true: 解析成功; false: 解析失败
local function trade_parse_request(ApmData)

    -- 流水号
    s_seq_no = ApmXml.getValue(t_xml_tree, "/service/sys-header/data[@name=\"SYS_HEAD\"]/struct/data[@name=\"CONSUMER_SEQ_NO\"]/field/text()");
    ApmData.replaceField("transaction.code", s_seq_no == nil and "" or string.trim(s_seq_no))

    -- 交易名
    s_type_name = ApmXml.getValue(t_xml_tree, "/service/sys-header/data[@name=\"SYS_HEAD\"]/struct/data[@name=\"SERVICE_CODE\"]/field/text()");
    ApmData.replaceField("transaction.type_code", s_type_name == nil and "未知" or string.trim(s_type_name))
    ApmData.replaceField("transaction.type_name", s_type_name == nil and "未知" or string.trim(s_type_name))

    s_channel_id = ApmXml.getValue(t_xml_tree, "/service/sys-header/data[@name=\"SYS_HEAD\"]/struct/data[@name=\"SOURCE_TYPE\"]/field/text()");
    if s_channel_id == nil then
        s_channel_id = "未知"
    else
        local s_channel_id_in_arr = arr_channel_id[s_channel_id];
        if s_channel_id_in_arr == nil then
        else
            s_channel_id = s_channel_id_in_arr
        end
    end
    ApmData.replaceField("transaction.channel_code", s_channel_id)
    ApmData.replaceField("transaction.channel_name", s_channel_id)

    return true;
end

--- 解析响应
-- return
-- true: 解析成功; false: 解析失败
local function trade_parse_response(ApmData)

    -- 交易返回代码
    s_rspcode = ApmXml.getValue(t_xml_tree, "/service/sys-header/data[@name=\"SYS_HEAD\"]/struct/data[@name=\"RET\"]/array/struct[1]/data[@name=\"RET_CODE\"]/field/text()");
    if s_rspcode ~= nil then
        s_rspcode = string.trim(s_rspcode);
        ApmData.replaceField("response.code_string", s_rspcode);
        ApmData.delFields("response.code")
        ApmData.delFields("response.error_message")
    end

    -- 交易返回信息
    s_rspmsg = ApmXml.getValue(t_xml_tree, "/service/sys-header/data[@name=\"SYS_HEAD\"]/struct/data[@name=\"RET\"]/array/struct[1]/data[@name=\"RET_MSG\"]/field/text()");
    if s_rspmsg ~= nil then
        s_rspmsg = string.trim(s_rspmsg);
        ApmData.replaceField("response.error_message", s_rspmsg);
    end

    return true;
end

--- main
function post_analysis()
    local ApmData = require("ApmData");
    if ApmData.getL7Proto() ~= 80 then return end

    local s_em_type = ApmData.getMsgType();
    if s_em_type == nil then return end

    local s_content_type, s_http_body;

    if s_em_type == 0 then -- 请求
        s_content_type = ApmData.getField("request.http.header.content-type", 1);
        s_http_body = ApmData.getField("request.http.body.1", 1);
        if s_content_type ~= nil and s_http_body ~= nil
        then
            s_http_body = string.trim(s_http_body);
            if protocol_detect(s_http_body) then
                trade_parse_request(ApmData);
            end
        end
    elseif s_em_type == 1 then -- 响应
        s_content_type = ApmData.getField("request.http.header.content-type", 1);
        s_http_body = ApmData.getField("request.http.body.1", 1);
        if s_content_type ~= nil and s_http_body ~= nil then
            s_message_req = string.trim(s_http_body);
            if protocol_detect(s_message_req) then
                trade_parse_request(ApmData);
            end
        end

        s_http_body = ApmData.getField("response.http.body.1", 1);
        if s_http_body ~= nil then
            s_message_resp = string.trim(s_http_body);
            if protocol_detect(s_message_resp) then
                trade_parse_response(ApmData);
            end
        end

        logInfo("ESB(%s:%d->%s:%d) 流水号:%s|交易名:%s|交易渠道:%s|返回码:%s|%s",
            ApmData.getSrcIp(),
            ApmData.getSrcPort(),
            ApmData.getDstIp(),
            ApmData.getDstPort(),
            s_seq_no,
            s_type_name,
            s_channel_id,
            s_rspcode,
            s_rspmsg == nil and "" or s_rspmsg)

        if s_seq_no == nil or
            s_type_name == nil or
            s_channel_id == nil or
            s_rspcode == nil then
            logError("ESB:REQ:[%s]\nRESP:[%s]", s_message_req, s_message_resp)
        end
    end

    return;
end
